const EOF = Symbol('EOF');
let currentToken = null,currentAttribute = null,currentTextNode = null;
let stack = [{type:"documnet",children:[]}];
const layoyt = require('./layout.js')
function emit(token){
    
    let top = stack[stack.length -1];
    if(token.type == "startTag"){
        let element = {
            type:"element",
            children:[],
            attributes:[]
        };
        element.tagNam = token.tagNam;
        for (let p in token) {
            if(p != "type" && p != "tagName"){
                element.attributes.push({
                    name:p,
                    value:token[p]
                });
            }
        }
        top.children.push(element);
        element.parent = top;
        if(!token.isSelfClosing){
            stack.push(element);
        }
        currentTextNode = null;

    }else if(token.type == "endTag"){
        if(top.tagNam != token.tagNam){
            throw new Error("Tasg start end doesn't match !")
        }else{
            if(top.tagNam == 'style'){
                addCssRule(top.children[0].content);
            }
            layoyt(top);
            stack.pop();
        }
        currentTextNode = null;
    }else if(token.type == "text"){
        if(currentTextNode == null){
            currentTextNode = {
                type:"text",
                content:""
            }
            top.children.push(currentTextNode);
        }
        currentTextNode.content += token.content;
    }
}

function data(c){
    if(c == '<'){
        return tagOpen;
    }else if(c == EOF){
        emit({type:"EOF"});
        return ;
    }else{
        emit({content:c});
        return data;
    }
}

function state(c){
    if(c == '<'){
        return tagOpen;
    }else if(c == EOF){
        return ;
    }else{
        return data;
    }
}

function tagOpen(c){
    if(c == '/'){
        return endTagOPen;
    }else if(c.match(/^[z-aA-Z]$/)){
        currentToken = {
            type:"startTag",
            tagNam:""
        }
        return tagNam(c);
    }else{
        return data;
    }
}

function endTagOPen(c){
    if(c.match(/^[a-zA-z]$/)){
        currentToken = {
            type:"endTag",
            tagNam:""
        }
        return tagNam(c);
    }else if(c == '>'){

    }else if(c == EOF){
       
    }else{
        
    }
}

function tagNam(c){
    if(c.match()){
        return beforeAttributeName;
    }else if(c.match(/^[a-zA-Z]$/)){
        currentToken.tagNam += c;
        return tagNam;
    }else if(c == "/"){
        return selfClosingStartTag;
    }else if(c == ">"){
        emit(currentToken);
        return data;
    }else{
        return tagNam;
    }
}

function beforeAttributeName(c){
    if(c.match(/^[\t\n\f ]$/)){
        return beforeAttributeName;
    }else if(c == ">" || c == "/" || c == EOF){

        return afterAttributeName(c);
    }else if(c == "="){
        return beforeAttributeName;
    }else{
        currentAttribute = {
            name:"",
            value:""
        }
        return attributeName(c);
    }
}

function attributeName(c){
    if(c.match(/^[\t\n\f ]$/) || c == "/" || c == ">" || c == EOF){
        return afterAttributeName(c);
    }else if(c == "="){
        return beforeAttributeValue;
    }else if(c == "\u0000"){

    }else if(c == "\"" || c == "'" || c == "<"){

    }else{
        currentAttribute += c;
        return attributeName;
    }
}

function beforeAttributeValue(c){
    if(c.match(/^[\t\n\f ]$/) || c == "/" || c == ">" || c == EOF){
        return beforeAttributeValue;
    }else if(c == "\""){
        return doubleQuotedAttributeValue;
    }else if(c == "\'"){
        return singleQuotedAttributeValue;
    }else if(c == ">"){

    }else{
        return UpQuotedAttributeValue;
    }
}

function doubleQuotedAttributeValue(c){
    if(c == "\""){
        currentToken[currentAttribute.name] = currentAttribute.value;
        return afterQuotedAttributeValue;
    }else if(c == "\u0000"){

    }else if(c == EOF){

    }else {
        currentAttribute.value += c;
        return doubleQuotedAttributeValue;
    }
}

function singleQuotedAttributeValue(c){
    if(c == "\'"){
        currentToken[currentAttribute.name] = currentAttribute.value;
        return afterQuotedAttributeValue;
    }else if(c == "\u0000"){

    }else if(c == EOF){

    }else{
        currentAttribute.value += c;
        return doubleQuotedAttributeValue;
    }
}

function UpQuotedAttributeValue(c){
    if(c.match(/^[\t\n\f ]$/)){
        currentToken[currentAttribute.name] = currentAttribute.value;
    }else if(c == "\u0000"){

    }else if(c == EOF){

    }else if(c == "\"" || c == "'" || c == "<" || c == "=" || c == "`"){

    }else{
        currentAttribute.value += c;
        return UpQuotedAttributeValue;
    }
}

function selfClosingStartTag(c){
    if(c == ">"){
        currentToken.isSelfClosing = true;
        return data;
    }else if(c == "EOF"){

    }else{

    }
}

module.exports.parserHTML = function parserHTML(html){
    let state = data;
    for(let c of html){
        state = state(c);
    }
    state = state(EOF);
    return stack[0];
}